﻿using BooksAPI.DTOs;
using BooksAPI.Models;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;

namespace BooksAPI.Controllers
{
    [RoutePrefix("api/Books")]
    public class BooksController : ApiController
    {
        private SqlSugarClient dbContext = DBFactory.DefaultDbContext;

        private static readonly Expression<Func<Book, BooksDto>> AsBooksDto =
            x => new BooksDto
            {
                Author = x.Author.Name,
                Genre = x.Genre,
                Title = x.Title
            };

        [Route("")]
        [HttpGet]
        public IEnumerable<BooksDto> GetBooks()
        {
            return dbContext.Queryable<Book, Author>((bk, au) => bk.AuthorID == au.AuthorID)
                            .Select((bk, au) => new BooksDto
                            {
                                Author = au.Name,
                                Genre = bk.Genre,
                                Title = bk.Title
                            }).ToList();
        }

        [Route("{bookID:int}")]
        [HttpGet]
        public async Task<IHttpActionResult> GetBook(int bookID)
        {
            BooksDto book = await dbContext.Queryable<Book, Author>((bk, au) => bk.AuthorID == au.AuthorID)
                            .Where((bk, au) => bk.BookID == bookID)
                            .Select((bk, au) => new BooksDto
                            {
                                Author = au.Name,
                                Genre = bk.Genre,
                                Title = bk.Title
                            })
                            .FirstAsync();
            if (book == null)
            {
                return NotFound();
            }
            else
            {
                return Ok(book);
            }
        }

        [Route("{bookID:int}/detail")]
        [HttpGet]
        public async Task<IHttpActionResult> GetBookDetail(int bookID)
        {
            BooksDetailDto bookDetail = await dbContext.Queryable<Book, Author>((bk, au) => bk.AuthorID == au.AuthorID)
                            .Where((bk, au) => bk.BookID == bookID)
                            .Select((bk, au) => new BooksDetailDto
                            {
                                Author = au.Name,
                                Description = bk.Description,
                                Genre = bk.Genre,
                                Price = bk.Price,
                                PublishDate = bk.PublishDate,
                                Title = bk.Title
                            })
                            .FirstAsync();
            if(bookDetail == null)
            {
                return NotFound();
            }
            else
            {
                return Ok(bookDetail);
            }
        }

        [Route("{genre}")]
        [HttpGet]
        public IEnumerable<BooksDto> GetBooksByGenre(string genre)
        {
            return dbContext.Queryable<Book, Author>((bk, au) => bk.AuthorID == au.AuthorID)
                            .Where((bk,au) => bk.Genre == genre)
                            .Select((bk, au) => new BooksDto
                            {
                                Author = au.Name,
                                Genre = bk.Genre,
                                Title = bk.Title
                            }).ToList();
        }

        [Route("~/api/authors/{authorID:int}/books")]
        [HttpGet]
        public IEnumerable<BooksDto> GetBooksByAuthor(int authorID)
        {
            return dbContext.Queryable<Book, Author>((bk, au) => bk.AuthorID == au.AuthorID)
                            .Where((bk, au) => au.AuthorID == authorID)
                            .Select((bk, au) => new BooksDto
                            {
                                Author = au.Name,
                                Genre = bk.Genre,
                                Title = bk.Title
                            }).ToList();
        }

        [Route("date/{publishDate:datetime:regex(\\d{4}-\\d{2}-\\d{2})}")]
        [Route("date/{*publishDate:datetime:regex(\\d{4}/\\d{2}/\\d{2})}")]
        [HttpGet]
        public IEnumerable<BooksDto> GetBooks(DateTime publishDate)
        {
            return dbContext.Queryable<Book, Author>((bk, au) => bk.AuthorID == au.AuthorID)
                           .Where((bk, au) => SqlFunc.DateIsSame(bk.PublishDate,publishDate))
                           .Select((bk, au) => new BooksDto
                           {
                               Author = au.Name,
                               Genre = bk.Genre,
                               Title = bk.Title
                           }).ToList();
        }
            
    }
}
